use crate::hot100::base::{ListNode, Vec2ListNode};

#[test]
fn test_add_two_numbers() {
    let node = ListNode::new(-1);

    assert_eq!(
        add_two_numbers(node.from_vec(vec![2, 4, 3]), node.from_vec(vec![5, 6, 4])),
        node.from_vec(vec![7, 0, 8])
    );

    assert_eq!(
        add_two_numbers(node.from_vec(vec![0]), node.from_vec(vec![0])),
        node.from_vec(vec![0])
    );

    assert_eq!(
        add_two_numbers(
            node.from_vec(vec![9, 9, 9, 9, 9, 9, 9]),
            node.from_vec(vec![9, 9, 9, 9])
        ),
        node.from_vec(vec![8, 9, 9, 9, 0, 0, 0, 1])
    );
}
/*
   2. 两数相加
   给你两个 非空 的链表，表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的，并且每个节点只能存储 一位 数字。
   请你将两个数相加，并以相同形式返回一个表示和的链表。
   你可以假设除了数字 0 之外，这两个数都不会以 0 开头。

   示例 1：
   输入：l1 = [2,4,3], l2 = [5,6,4]
   输出：[7,0,8]
   解释：342 + 465 = 807.

   示例 2：
   输入：l1 = [0], l2 = [0]
   输出：[0]

   示例 3：
   输入：l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
   输出：[8,9,9,9,0,0,0,1]


   提示：
   每个链表中的节点数在范围 [1, 100] 内
   0 <= Node.val <= 9
   题目数据保证列表表示的数字不含前导零
*/
pub fn add_two_numbers(
    l1: Option<Box<ListNode>>,
    l2: Option<Box<ListNode>>,
) -> Option<Box<ListNode>> {
    let mut result = None;
    let mut tail = &mut result;
    let mut t = (l1, l2, 0, 0); // (list1, list2, sum, carry)
    loop {
        t = match t {
            (None, None, _, 0) => break,
            (None, None, _, carry) => (None, None, carry, 0),
            (Some(list), None, _, carry) | (None, Some(list), _, carry)
                if list.val + carry >= 10 =>
            {
                (list.next, None, list.val + carry - 10, 1)
            }
            (Some(list), None, _, carry) | (None, Some(list), _, carry) => {
                (list.next, None, list.val + carry, 0)
            }
            (Some(l1), Some(l2), _, carry) if l1.val + l2.val + carry >= 10 => {
                (l1.next, l2.next, l1.val + l2.val + carry - 10, 1)
            }
            (Some(l1), Some(l2), _, carry) => (l1.next, l2.next, l1.val + l2.val + carry, 0),
        };

        *tail = Some(Box::new(ListNode::new(t.2)));
        tail = &mut tail.as_mut().unwrap().next;
    }
    result
}

// pub fn add_two_numbers2(
//     l1: Option<Box<ListNode>>,
//     l2: Option<Box<ListNode>>,
// ) -> Option<Box<ListNode>> {
//     let mut res = Some(Box::new(ListNode::new(0)));
//     let mut current = res.as_mut();
//     let (mut p, mut q, mut carry) = (l1, l2, 0);

//     while p.is_some() || q.is_some() {
//         let mut total = carry;

//         if let Some(v) = p {
//             total += v.val;
//             p = v.next;
//         }
//         if let Some(v) = q {
//             total += v.val;
//             q = v.next;
//         }

//         carry = total / 10;

//         if let Some(cur) = current {
//             cur.next = Some(Box::new(ListNode::new(total % 10)));
//             current = cur.next.as_mut();
//         }
//     }

//     if carry > 0 {
//         current.unwrap().next = Some(Box::new(ListNode::new(1)));
//     }
//     return res.unwrap().next;
// }
